﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Elsa.CSharp.Activities;
using Elsa.Extensions;
using Elsa.JavaScript.Activities;
using Elsa.JavaScript.Models;
using Elsa.Workflows;
using Elsa.Workflows.Activities;
using Elsa.Workflows.Memory;
using Elsa.Workflows.Models;
using Newtonsoft.Json;
using T.FAS.Runtime.MF.Activities;
using T.FAS.Runtime.MF.Activities.Helper;
using T.FAS.Runtime.MF.Entity;
using T.FAS.Runtime.MF.SPI;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace T.FAS.Runtime.MF.Activities.Nodes
{

    // 代码节点
    public class CodeNode : NodeBase, INodeMapper
    {
        [JsonProperty("data")]
        public new CodeNodeData Data { get; set; }

        public List<Variable> Variables { get; set; } = new List<Variable>();
        public List<OutputDefinition> Outputs { get; set; }
        public List<InputDefinition> Inputs { get; set; } = new List<InputDefinition>();
        public override List<UserVariable> NodeInputOutputVariables
        {
            get
            {
                if (Data.OutputVariables == null) return new List<UserVariable>();
                Data.OutputVariables.ForEach(v =>
                {
                    SetVariableInfo(v);
                });
                return Data.OutputVariables;
            }
        }

        private void SetVariableInfo(UserVariable v)
        {
            if (string.IsNullOrEmpty(v.ActivityID))
            {
                v.ActivityID = Id;
                v.CompositeVarName = $"{Id}:{v.VariableName}";
                v.CompositeVarName = v.CompositeVarName.Replace("-", "").Replace(":", "");
            }

        }
        public IActivity MapToActivity()
        {
            IActivity activity = null;

            var jsActivity = new JavaScriptActivity() { Id = Id, Name = Data.Label };
            jsActivity.Script = Data.Code;
            var activityOutputVariables = new List<Variable>();
            //输出变量
            if (Data.OutputVariables != null && Data.OutputVariables.Count() > 0)
            {
                jsActivity.OutputVariables = new Dictionary<string, Variable>();

                //var resultVariableItem = new UserVariable()
                //{
                //    ActivityID = Id,
                //    CompositeVarName=$"{Id.Replace("-", "")}Result",
                //    Type="object"
                //};
                //var resultVariable = VariableHelper.GenerateVariable(resultVariableItem);
                //jsActivity.Result = new(resultVariable);

                //Variables.Add(resultVariable);

                foreach (var varItem in Data.OutputVariables)
                {
                    if (string.IsNullOrEmpty(varItem.VariableName)) continue;
                    SetVariableInfo(varItem);
                    var variable = VariableHelper.GenerateVariable(varItem);
                    Variables.Add(variable);

                    jsActivity.OutputVariables[varItem.VariableName] = variable;

                    //为了向迭代节点返回值，此处特意增加一个变量，用于处理节点的返回值数组
                    var iterationResultVarItem = new UserVariable() { CompositeVarName = $"{varItem.CompositeVarName}{MFConst.IterationResultVariableSuffix}", Type = varItem.ValueType };
                    var iterationResultVar = VariableHelper.GenerateVariable(iterationResultVarItem);
                    Variables.Add(iterationResultVar);
                }
            }
            //输入参数
            if (Data.InputVariables != null && Data.InputVariables.Count() > 0)
            {
                ReplaceAllVariableName(Data.InputVariables);

                jsActivity.ParamList = new List<BranchCondition>();
                foreach (var item in Data.InputVariables)
                {
                    if (string.IsNullOrEmpty(item.CodeParamName)) continue;
                    if (string.IsNullOrEmpty(item.VariableName)) continue;

                    var promptVariableName = item.CodeParamName;
                    var variable = item.VariableName;
                    if (!string.IsNullOrEmpty(item.NodeID))
                    {
                        if (item.NodeID.StartsWith("iteration"))
                        {
                            if (item.VariableName == "item")
                            {
                                variable = "CurrentValue";
                            }
                            else if (item.VariableName == "index")
                            {
                                variable = "CurrentIndex";
                            }
                        }
                    }


                    var expression = string.Empty;
                    expression = ActivityHelper.GetVariableExpression(variable, item.Type, false);
                    //var varSelectors = variable.Split('.');
                    //var varItem = varSelectors[0];
                    //if (varSelectors.Length > 1 || (varSelectors.Count() == 1 && item.Type == "record"))
                    //{
                    //    expression = $"let {varItem} = JSON.parse(variables.{varItem});{varItem};";
                    //}
                    //else
                    //{
                    //    expression = $"let {varItem} = variables.{varItem};{varItem};";
                    //}
                    jsActivity.ParamList.Add(new BranchCondition { Label = promptVariableName, Condition = JavaScriptExpression.Create(expression) });

                }
            }
            activity = jsActivity;

            activity.Metadata = DesignerMeta;
            return activity;
        }
        private void ReplaceAllVariableName(List<UserVariable> Variables)
        {
            foreach (var variable in Variables)
            {
                //如果节点参数的来源于迭代节点的output，则取out对应的节点的参数，不直接使用output
                if (variable.VariableName == "output" && variable.NodeID.StartsWith("iteration"))
                {
                    // var outputVarInfo = (this.BelongTo.NodeInputOutputVariables ?? new List<UserVariable>()).Find(t => t.VariableName == variable.VariableName && t.ActivityID == variable.NodeID);
                    var outputVarInfo = ActivityHelper.GetSourceVariable(this, $"{variable.VariableValue}{MFConst.IterationResultVariableSuffix}", variable.VariableNodeID);
                    if (outputVarInfo!=null)
                    {
                        variable.VariableName = outputVarInfo.VariableValue;
                        variable.NodeID = outputVarInfo.VariableNodeID;
                        variable.Type = outputVarInfo.Type;
                    }
                   
                }

                if (string.IsNullOrEmpty(variable.VariableName)) continue;
                /*
                var varSelectors = variable.VariableName.Split('.');
                var varItem = varSelectors[0];

                //从整个工作流中获取应的变量信息
                var varInfo = (this.BelongTo.NodeInputOutputVariables ?? new List<UserVariable>()).Find(t => t.VariableName == varItem && t.ActivityID == variable.NodeID);
                if (varInfo == null) { continue; }
                var varName = varInfo.CompositeVarName;
                varSelectors[0] = varName;
                variable.VariableName = string.Join(".", varSelectors);
                */
                variable.VariableName = ActivityHelper.GetSourceVariableRealName(this, variable.VariableName, variable.NodeID);
            }
        }
    }


    public class CodeNodeData
    {
        [JsonProperty("label")]
        public string Label { get; set; }

        [JsonProperty("description")]
        public string Description { get; set; }

        [JsonProperty("language")]
        public string Language { get; set; }

        [JsonProperty("code")]
        public string Code { get; set; }

        [JsonProperty("inputFields")]
        public List<UserVariable> InputVariables { get; set; } 

        [JsonProperty("outputFields")]
        public List<UserVariable> OutputVariables { get; set; }

        [JsonProperty("enableTimeout")]
        public bool EnableTimeout { get; set; }

        [JsonProperty("timeout")]
        public int Timeout { get; set; }
    }
}
